package com.mytijian.code.service.helper;

import com.alibaba.fastjson.JSON;
import com.mytijian.code.exceptions.MashangExceptionEnum;
import com.mytijian.code.model.Mcode;
import com.mytijian.code.model.MerchantOrder;
import com.mytijian.exception.BizException;
import com.mytijian.exception.BizSystemException;
import com.taobao.api.ApiException;
import com.taobao.api.DefaultTaobaoClient;
import com.taobao.api.TaobaoClient;
import com.taobao.api.TaobaoResponse;
import com.taobao.api.request.EticketMerchantMaAvailableRequest;
import com.taobao.api.request.EticketMerchantMaConsumeRequest;
import com.taobao.api.request.EticketMerchantMaResendRequest;
import com.taobao.api.request.EticketMerchantMaSendRequest;
import com.taobao.api.response.EticketMerchantMaAvailableResponse;
import com.taobao.api.response.EticketMerchantMaConsumeResponse;
import com.taobao.api.response.EticketMerchantMaResendResponse;
import com.taobao.api.response.EticketMerchantMaSendResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * Created by shjh on 2017/9/18.
 */
@Component
public class ToTaobaoHelper {
	@Value("${aliApp.codeMerchant.url}")
	private String url;
	@Value("${aliApp.codeMerchant.appKey}")
	private String appkey;
	@Value("${aliApp.codeMerchant.appSecret}")
	private String secret;
	@Value("${aliApp.codeMerchant.sessionKey}")
	private String sessionKey;
	@Value("${aliApp.codeMerchant.refreshToken}")
	private String refresh_token;

	private Logger logger = LoggerFactory.getLogger(ToTaobaoHelper.class);

	public String CONSUME_ERROR_CODE = "15"; // 重复核销的异常码
	private String SESSIONKEY_EXPIRED_CODE = "27"; //sessionKey授权时间过期异常码
	private String OVERCLOCKING_CODE = "7"; //调用超频异常码
	// 码可核销次数
	private Long CODE_WRITE_OFF_NUM = 1L;

	/**
	 * 调用淘宝核销
	 * @param merchantOrder
	 * @param isCheckResult 是否需要对核销结果进行校验
	 */
	public void consume(MerchantOrder merchantOrder, String code, boolean isCheckResult) {

		EticketMerchantMaConsumeResponse rsp = consumeWithException(createRequest(merchantOrder, code));
		if (!rsp.isSuccess()) {
			notSuccessMonitor(rsp);
		}
		if (!rsp.isSuccess() && !rsp.getErrorCode().equals(CONSUME_ERROR_CODE)) {
			logger.warn("!!!重新核销回调异常code={}", code);
		}
		if (isCheckResult && !rsp.isSuccess()) {
			throw new BizException(MashangExceptionEnum.CONSUME_FAIL.getErrorCode(), rsp.getRetMsg());
		}
	}

	private EticketMerchantMaConsumeResponse consumeWithException(EticketMerchantMaConsumeRequest req) {
		try {
			logger.info("调用淘宝核销接口开始param=[{}]", JSON.toJSONString(req));
			TaobaoClient client = new DefaultTaobaoClient(url, appkey, secret);
			EticketMerchantMaConsumeResponse rsp = client.execute(req, sessionKey);
			logger.info("调用淘宝核销接口用结束 result=[{}]", rsp.getBody());
			return rsp;
		} catch (ApiException ex) {
			logger.error("回调淘宝核销接口异常", ex);
			throw new BizException(MashangExceptionEnum.CONSUME_FAIL);
		}
	}

	private EticketMerchantMaConsumeRequest createRequest(MerchantOrder merchantOrder, String code) {
		EticketMerchantMaConsumeRequest req = new EticketMerchantMaConsumeRequest();
		req.setBizType(Long.valueOf(merchantOrder.getBizType()));
		req.setCode(code);
		req.setOuterId(merchantOrder.getOuterId());
		req.setToken(merchantOrder.getToken());
		req.setConsumeNum(CODE_WRITE_OFF_NUM);
		req.setSerialNum(UUID.randomUUID().toString());
		return req;
	}

	/**
	 * 核销前校验
	 */
	public void available(String code, MerchantOrder order) {
		
		EticketMerchantMaAvailableRequest req = new EticketMerchantMaAvailableRequest();
		req.setBizType(Long.valueOf(order.getBizType()));
		req.setCode(code);
		req.setOuterId(order.getOuterId());
		req.setToken(order.getToken());
		req.setConsumeNum(CODE_WRITE_OFF_NUM);
		
		try {
			TaobaoClient client = new DefaultTaobaoClient(url, appkey, secret);
			EticketMerchantMaAvailableResponse rsp = client.execute(req, sessionKey);
			if (!rsp.isSuccess()) {
				notSuccessMonitor(rsp);
				throw new BizException(MashangExceptionEnum.CONSUME_AVAILABLE_FAIL.getErrorCode(), rsp.getSubMsg());
			}
			logger.info("核销前检验接口返回结果" + rsp.getBody());
		} catch (ApiException e) {
			logger.error("回调淘宝核销前校验接口异常", e);
			throw new BizException(MashangExceptionEnum.CONSUME_AVAILABLE_FAIL);
		}
	}

	/**
	 * 码商发码成功回调接口
	 */
	public void send(MerchantOrder order, List<Mcode> mcodes) {
		try {
			EticketMerchantMaSendRequest req = new EticketMerchantMaSendRequest();
			req.setToken(order.getToken());
			req.setOuterId(order.getOuterId());
			List<EticketMerchantMaSendRequest.IsvMa> isvMas = buildSendIsvMasList(mcodes);
			req.setIsvMaList(isvMas);
			EticketMerchantMaSendResponse rsp = doSend(req);
			if (!rsp.isSuccess()) {
				notSuccessMonitor(rsp);
				logger.warn("!!! 码商平台校验订单[outId={}]发码无效codes=[{}]", req.getOuterId(), req.getIsvMaList());
			}
		} catch (ApiException e) {
			throw new BizSystemException(MashangExceptionEnum.NOTIFY_CODE_MERCHANT_PLATFORM_FAIL, e);
		}
	}
	
	private List<EticketMerchantMaSendRequest.IsvMa> buildSendIsvMasList(List<Mcode> mcodes) {
		List<EticketMerchantMaSendRequest.IsvMa> isvMas = new ArrayList<>();
		// 码可核销次数
		mcodes.stream().forEach(mcode -> {
			EticketMerchantMaSendRequest.IsvMa isvMa = new EticketMerchantMaSendRequest.IsvMa();
			isvMa.setCode(mcode.getCode());
			isvMa.setNum(CODE_WRITE_OFF_NUM);
			isvMas.add(isvMa);
		});
		return isvMas;
	}

	/**
	 * 码商发码成功回调接口
	 */
	public EticketMerchantMaSendResponse doSend(EticketMerchantMaSendRequest req) throws ApiException {
		logger.info("发码成功回调接口调用param: " + JSON.toJSONString(req));
		TaobaoClient client = new DefaultTaobaoClient(url, appkey, secret);
		EticketMerchantMaSendResponse rsp = client.execute(req, sessionKey);
		logger.info("发码成功回调接口结果返回" + rsp.getBody());
		return rsp;
	}

	/**
	 * 电子凭证重发回调接口
	 */
	public void resend(MerchantOrder order, List<Mcode> codes) {
		try {
			List<EticketMerchantMaResendRequest.IsvMa> isvMas = buildresendIsvMasList(codes);
			if(order.getAvailableNum() != isvMas.size()){
				throw new BizException(MashangExceptionEnum.SEND_CODE_NUM_DIFFERENT);
			}
			EticketMerchantMaResendRequest req = new EticketMerchantMaResendRequest();
			req.setIsvMaList(isvMas);
			req.setOuterId(order.getOuterId());
			req.setBizType(Long.valueOf(order.getBizType()));
			req.setToken(order.getToken());
			EticketMerchantMaResendResponse rsp = doResend(req);
			if (!rsp.isSuccess()) {
				notSuccessMonitor(rsp);
				logger.warn("!!! 码商平台校验订单[outId={}]发码无效codes=[{}]", req.getOuterId(), req.getIsvMaList());
			}
		} catch (ApiException e) {
			throw new BizSystemException(MashangExceptionEnum.NOTIFY_CODE_MERCHANT_PLATFORM_FAIL, e);
		}
	}
	
	private List<EticketMerchantMaResendRequest.IsvMa> buildresendIsvMasList(List<Mcode> codes) {
		List<EticketMerchantMaResendRequest.IsvMa> isvMas = new ArrayList<>();
		for (Mcode mcode : codes) {
				EticketMerchantMaResendRequest.IsvMa isvMa = new EticketMerchantMaResendRequest.IsvMa();
				isvMa.setCode(mcode.getCode());
				isvMa.setNum(CODE_WRITE_OFF_NUM);
				isvMas.add(isvMa);
		}
		return isvMas;
	}

	/**
	 * 电子凭证重发回调接口
	 */
	public EticketMerchantMaResendResponse doResend(EticketMerchantMaResendRequest req) throws ApiException {
		logger.info("重新发码成功回调接口调用param: " + JSON.toJSONString(req));
		TaobaoClient client = new DefaultTaobaoClient(url, appkey, secret);
		EticketMerchantMaResendResponse rsp = client.execute(req, sessionKey);
		logger.info("重新发码成功回调接口结果返回" + rsp.getBody());
		return rsp;
	}

	/**
	 * 调用失败监控处理
	 * @param response
     */
	private void notSuccessMonitor(TaobaoResponse response) {
		if (SESSIONKEY_EXPIRED_CODE.equals(response.getErrorCode())) {
			logger.error("!!! sessionKey授权时间过期,sessionKey={}", sessionKey);
		}
		if (OVERCLOCKING_CODE.equals(response.getErrorCode())) {
			logger.error("!!! 服务调用超频");
		}
	}
}
